package com.mrjy.wechat.controller;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.mrjy.common.entity.ShareMemberInfo;
import com.mrjy.common.entity.UserInfo;
import com.mrjy.common.entity.WxAccountFans;
import com.mrjy.common.entity.WxMsgNews;
import com.mrjy.common.util.GlobalConstant;
import com.mrjy.maintain.bo.IUserInfoBo;
import com.mrjy.share.bo.IShareMemberBo;
import com.mrjy.wechat.bo.MyService;
import com.mrjy.wechat.dto.Material;
import com.mrjy.wechat.dto.MaterialArticle;
import com.mrjy.wechat.dto.MaterialItem;
import com.mrjy.wechat.dto.MsgRequest;
import com.mrjy.wechat.dto.TemplateMessage;
import com.mrjy.wechat.page.Pagination;
import com.mrjy.wechat.process.AccessToken;
import com.mrjy.wechat.process.ErrCode;
import com.mrjy.wechat.process.MediaType;
import com.mrjy.wechat.process.MpAccount;
import com.mrjy.wechat.process.MsgXmlUtil;
import com.mrjy.wechat.process.WxApiClient;
import com.mrjy.wechat.process.WxMemoryCacheClient;
import com.mrjy.wechat.process.WxSign;
import com.mrjy.wechat.util.DateUtil;
import com.mrjy.wechat.util.JsonView;
import com.mrjy.wechat.util.wx.SignUtil;
import com.mrjy.wechat.util.UploadUtil;

/**
 * 微信与开发者服务器交互接口
 */
@Controller
@RequestMapping("/wxapi")
public class WxApiCtrl {

	@Autowired
	private MyService myService;
	
	@Autowired
	private IUserInfoBo userInfoBo;
	
	@Autowired
	private IShareMemberBo shareMemberBo;

	/**
	 * .f GET请求：进行URL、Tocken 认证； 1. 将token、timestamp、nonce三个参数进行字典序排序 2.
	 * 将三个参数字符串拼接成一个字符串进行sha1加密 3. 开发者获得加密后的字符串可与signature对比，标识该请求来源于微信
	 * 
	 * @throws IOException
	 */
	@RequestMapping(value = "/message/{account}", method = RequestMethod.GET)
	public void doGet(HttpServletRequest request, HttpServletResponse response,
			@PathVariable String account) throws IOException {
		String token = myService.getAccount(account).getToken();// 获取token，进行验证；
		String signature = request.getParameter("signature");// 微信加密签名
		String timestamp = request.getParameter("timestamp");// 时间戳
		String nonce = request.getParameter("nonce");// 随机数
		String echostr = request.getParameter("echostr");// 随机字符串

		// 校验成功返回 echostr，成功成为开发者；否则返回error，接入失败
		if (SignUtil.validSign(signature, token, timestamp, nonce)) {
			response.getWriter().write(echostr);
		}
		response.getWriter().write("error");
	}

	/**
	 * .f POST 请求：进行消息处理；
	 * */
	@RequestMapping(value = "/message/{account}", method = RequestMethod.POST)
	public void doPost(HttpServletRequest request,
			HttpServletResponse response, @PathVariable String account) {
		// 处理用户和微信公众账号交互消息
		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount(account);
		if (mpAccount == null) {
			mpAccount = myService.getAccount(account);
		}
		try {
			MsgRequest msgRequest = MsgXmlUtil.parseXml(request);// 获取发送的消息
			response.setCharacterEncoding("utf-8");
			response.getWriter().write(
					myService.processMsg(msgRequest, mpAccount));
		} catch (Exception e) {
			e.printStackTrace();
			try {
				response.getWriter().write("error");
			} catch (IOException e1) {
				e1.printStackTrace();
			}
		}
	}

	// 创建微信公众账号菜单.f
	@RequestMapping(value = "/publishMenu/{account}")
	@ResponseBody
	public Object publishMenu(HttpServletRequest request, String gid,
			@PathVariable String account) {
		if (!StringUtils.isNotBlank(gid)) {
			return "gid is missing";
		}
		JSONObject rstObj = null;
		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount(account);
		if (mpAccount == null) {
			mpAccount = myService.getAccount(account);
		}
		if (mpAccount != null) {
			rstObj = myService.publishMenu(gid, mpAccount);
			if (rstObj != null) {// 成功，更新菜单组
				if (rstObj.containsKey("menu_id")) {
					return "ok";
				} else if (rstObj.containsKey("errcode")
						&& rstObj.getInt("errcode") == 0) {
					return "ok";
				}
			}
		}

		if (rstObj != null) {
			return ErrCode.errMsg(rstObj.getInt("errcode"));
		} else {
			return "error";
		}
	}

	// 删除微信公众账号菜单.f
	@RequestMapping(value = "/deleteMenu/{account}")
	@ResponseBody
	public Object deleteMenu(HttpServletRequest request,
			@PathVariable String account) {
		JSONObject rstObj = null;
		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount(account);
		if (mpAccount == null) {
			mpAccount = myService.getAccount(account);
		}
		if (mpAccount != null) {
			rstObj = myService.deleteMenu(mpAccount);
			if (rstObj != null && rstObj.getInt("errcode") == 0) {
				return "ok";
			}
		}
		if (rstObj != null) {
			return ErrCode.errMsg(rstObj.getInt("errcode"));
		} else {
			return "error";
		}
	}

	/**
	 * 获取用户列表 10条一次 .f
	 * 
	 * @param account
	 * @return
	 */
	@RequestMapping(value = "/syncAccountFansList/{account}")
	@ResponseBody
	public Object syncAccountFansList(@PathVariable String account) {
		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount(account);
		if (mpAccount == null) {
			mpAccount = myService.getAccount(account);
		}
		if (mpAccount != null) {
			int flag = myService.syncAccountFansList(mpAccount);
			if (flag == 0) {
				return "ok";
			} else if (flag == -1) {
				return "error";
			} else {
				return flag;
			}
		}
		return "ok";
	}

	// 根据用户的ID更新用户信息
	@RequestMapping(value = "/syncAccountFans/{account}")
	@ResponseBody
	public Object syncAccountFans(String openid, @PathVariable String account) {
		JsonView json = new JsonView();
		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount(account);
		if (mpAccount == null) {
			mpAccount = myService.getAccount(account);
		}
		if (mpAccount != null) {
			WxAccountFans fans = myService.syncAccountFans(openid, mpAccount,
					true);// 同时更新数据库+
			if (fans != null) {
				json.setMessage("获取成功");
				json.setData(fans);
				return json;
			}
		}
		json.setErrcode(1001);
		json.setMessage("获取失败");
		json.setData("获取失败");
		return json;
	}

	// 获取永久素材
	@RequestMapping(value = "/syncMaterials/{account}")
	public ModelAndView syncMaterials(Pagination<MaterialArticle> pagination,
			@PathVariable String account) {
		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount(account);
		if (mpAccount == null) {
			mpAccount = myService.getAccount(account);
		}

		ModelAndView mv = new ModelAndView("wxcms/materialPagination");
		Integer offset = pagination.getStart();
		Integer count = pagination.getPageSize();
		Material material = WxApiClient.syncBatchMaterial(MediaType.News,
				offset, count, mpAccount);
		if (material != null) {
			List<MaterialArticle> materialList = new ArrayList<MaterialArticle>();
			List<MaterialItem> itemList = material.getItems();
			if (itemList != null) {
				for (MaterialItem item : itemList) {
					MaterialArticle m = new MaterialArticle();
					if (item.getNewsItems() != null
							&& item.getNewsItems().size() > 0) {
						MaterialArticle ma = item.getNewsItems().get(0);// 用第一个图文的简介、标题、作者、url
						m.setAuthor(ma.getAuthor());
						m.setTitle(ma.getTitle());
						m.setUrl(ma.getUrl());
					}
					materialList.add(m);
				}
			}
			pagination.setTotalItemsCount(material.getTotalCount());
			pagination.setItems(materialList);
		}
		mv.addObject("page", pagination);
		mv.addObject("cur_nav", "material");
		return mv;
	}

	// 上传图文素材
	@RequestMapping(value = "/doUploadMaterial/{account}")
	@ResponseBody
	public Object doUploadMaterial(WxMsgNews msgNews,
			@PathVariable String account) {
		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount(account);
		if (mpAccount == null) {
			mpAccount = myService.getAccount(account);
		}
//		String rstMsg = "上传图文消息素材";
		List<WxMsgNews> msgNewsList = new ArrayList<WxMsgNews>();
//		msgNews.setUrl("https://www.baidu.com");
//		msgNews.setTitle("title");
//		msgNews.setAuthor("she");
//		msgNews.setFromurl("www.baidu.com");
//		msgNews.setPicPath("http://localhost:8080/mrjy/aa.jpg");
//		msgNews.setDescription("s");
		msgNewsList.add(msgNews);
		JSONObject rstObj = WxApiClient.uploadNews(msgNewsList, mpAccount);
		if (rstObj.containsKey("media_id")) {
			System.out.println(rstObj.getString("media_id"));
//			ModelAndView mv = new ModelAndView("common/success");
//			mv.addObject("successMsg",
//					"上传图文素材成功,素材 media_id : " + rstObj.getString("media_id"));
			return rstObj.getString("media_id");
		} else {
			System.out.println(rstObj);
//			rstMsg = ErrCode.errMsg(rstObj.getInt("errcode"));
		}
//		System.out.println(rstObj);
//		ModelAndView mv = new ModelAndView("common/failure");
//		mv.addObject("failureMsg", rstMsg);
		return null;
	}

	// 获取openid.f
	@RequestMapping(value = "/oauthOpenid/{account}")
	@ResponseBody
	public Object oauthOpenid(HttpServletRequest request,
			@PathVariable String account) {
		JsonView json = new JsonView();
		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount(account);
		if (mpAccount == null) {
			mpAccount = myService.getAccount(account);
		}
		if (mpAccount != null) {
//			System.out.println(request.getSession().getId());
			// 拦截器已经处理了缓存,这里直接取
			String openid = WxMemoryCacheClient.getOpenid(request.getSession()
					.getId());
			if (!StringUtils.isNotBlank(openid)) {
				String code = request.getParameter("code");
				JSONObject rstObj = myService.getOpenidByCode(code, mpAccount);
				if (rstObj != null) {
					if (rstObj.containsKey("openid")) {
						// 获得新的openid存到WxMemoryCacheClient里面
						openid = rstObj.getString("openid");
						WxMemoryCacheClient.setOpenid(request.getSession()
								.getId(), openid);
					}
				}
			}
			WxAccountFans fans = myService.syncAccountFans(openid, mpAccount,
					false);// 同时更新数据库
			if(fans==null){
				fans = new WxAccountFans();
				fans.setOpenId(openid);
			}
			json.setMessage("获取成功");
			json.setData(fans);
			return json;
		} else {
			json.setErrcode(1001);
			json.setMessage("获取失败");
			json.setData("获取失败");
			return json;
		}
	}

	/**
	 * 生成二维码.f
	 * 
	 * @param request
	 * @param num
	 *            二维码参数
	 * @return
	 */
	@RequestMapping(value = "/createQrcode/{account}", method = RequestMethod.POST)
	@ResponseBody
	public Object createQrcode(HttpServletRequest request, Integer num,
			@PathVariable String account) {
		JsonView jv = new JsonView();
		jv.setMessage("ok");
		Map map = new HashMap();
		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount(account);
		if (mpAccount == null) {
			mpAccount = myService.getAccount(account);
		}
		if (num != null) {
			byte[] qrcode = WxApiClient.createQRCode(60, num, mpAccount);// 有效期60s
			String url = UploadUtil.byteToImg(request.getServletContext()
					.getRealPath("/"), qrcode);
			map.put("qrcode", url);
		}
		map.put("cur_nav", "qrcode");
		map.put("num", num);
		jv.setData(map);
		return jv;
	}

	//根据opendid群发图文消息
	@RequestMapping(value = "/newsSendTextMsg/{account}", method = RequestMethod.POST)
	@ResponseBody
	public String newsSendTextMsg(HttpServletResponse response,String mediaId,@PathVariable String account){
		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount(account);
		
		if(mpAccount == null ){
			mpAccount = myService.getAccount(account);
		}
		String rstMsg = "根据openid群发图文消息失败";
		if(mpAccount != null){
			JSONArray openidList;
			// 获取关注者openid
			openidList = myService.syncAccountFansOpenidList(mpAccount);
			//根据openid群发图文消息
			JSONObject result = WxApiClient.newsSendTextByOpenIds(openidList, mediaId, mpAccount);

			if(result.getInt("errcode") != 0){
				return "failure";
			}else{
				return "success";
			}
			
//			try {
//				if(result.getInt("errcode") != 0){
//					response.getWriter().write("send failure");
//				}else{
//					response.getWriter().write("send success");
//				}
//			} catch (IOException e) {
//				e.printStackTrace();
//			}
		}
//		ModelAndView mv = new ModelAndView("common/failure");
//		mv.addObject("failureMsg", rstMsg);
		return "failure";
	}

	/**
	 * 群发文本消息.f
	 * 
	 * @param response
	 * @param openid
	 *            以逗号分隔多个openid
	 * @param content
	 *            文本内容
	 * @param account
	 */
	@RequestMapping(value = "/massSendTextMsg/{account}", method = RequestMethod.POST)
	public void massSendTextMsg(HttpServletResponse response, String openid,
			String content, @PathVariable String account) {
		// content = "群发文本消息";
		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount(account);
		if (mpAccount == null) {
			mpAccount = myService.getAccount(account);
		}
		if (mpAccount != null && !StringUtils.isBlank(openid)) {
			String[] openidarr = openid.split(",");
			List<String> openidList = new ArrayList<String>();
			Collections.addAll(openidList, openidarr);
			// 根据openid群发文本消息
			JSONObject result = WxApiClient.massSendTextByOpenIds(openidList,
					content, mpAccount);

			try {
				if (result.getInt("errcode") != 0) {
					response.getWriter().write("error");
				} else {
					response.getWriter().write("ok");
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 发送客服消息.f
	 * 
	 * @param openId
	 *            ： openid单个ID
	 * @param content
	 *            ： 消息内容
	 * @return
	 */
	@RequestMapping(value = "/sendCustomTextMsg/{account}", method = RequestMethod.POST)
	public void sendCustomTextMsg(HttpServletRequest request,
			HttpServletResponse response, String openid,
			@PathVariable String account, String content) {
		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount(account);
		if (mpAccount == null) {
			mpAccount = myService.getAccount(account);
		}
		// content = "测试客服消息";
		JSONObject result = WxApiClient.sendCustomTextMessage(openid, content,
				mpAccount);
		try {
			if (result.getInt("errcode") != 0) {
				result = WxApiClient.sendCustomTextMessage(openid, content,
						mpAccount);
				response.getWriter().write(result.toString());
			} else {
				response.getWriter().write("ok");
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 发送模板消息.f
	 * 
	 * @param openId
	 * @param content
	 * @return
	 */
	@RequestMapping(value = "/sendTemplateMessage/{account}", method = RequestMethod.POST)
	public void sendTemplateMessage(HttpServletRequest request,
			HttpServletResponse response, String openid,
			@PathVariable String account, String templateid) {
		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount(account);
		if (mpAccount == null) {
			mpAccount = myService.getAccount(account);
		}
		TemplateMessage tplMsg = new TemplateMessage();

		tplMsg.setOpenid(openid);
		// 微信公众号号的template id，开发者自行处理参数
		templateid = "DoSmI4FwHoJt5sJtMsRzxRSLPQhtZC_l9uetxWHglQ4";
		tplMsg.setTemplateId(templateid);
		/*
		 * 新建模板的内容 {{title.DATA}} 第二行:{{t2.DATA}} 第三行:{{t3.DATA}}
		 * 第四行:{{t4.DATA}} 第五行:{{t5.DATA}} {{foot.DATA}}
		 */
		tplMsg.setUrl("http://www.baidu.com");
		Map<String, String> dataMap = new HashMap<String, String>();
		dataMap.put("title", "模板的头");
		dataMap.put("t2", "不知道");
		dataMap.put("t3", "不知道");
		dataMap.put("t4", "不知道");
		dataMap.put("t5", "不知道");
		dataMap.put("foot", "时间：" + DateUtil.COMMON.getDateText(new Date()));
		tplMsg.setDataMap(dataMap);

		JSONObject result = WxApiClient.sendTemplateMessage(tplMsg, mpAccount);
		try {
			if (result.getInt("errcode") != 0) {
				response.getWriter().write("error");
			} else {
				response.getWriter().write("ok");
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 获取js ticket.f
	 * 
	 * @param request
	 * @param url
	 * @return
	 */
	@RequestMapping(value = "/jsTicket/{account}")
	@ResponseBody
	public String jsTicket(HttpServletRequest request, String url,
			@PathVariable String account) {
		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount(account);
		if (mpAccount == null) {
			mpAccount = myService.getAccount(account);
		}
		String jsTicket = WxApiClient.getJSTicket(mpAccount);
		WxSign sign = new WxSign(mpAccount.getAppid(), jsTicket, url);

		/*
		 * System.out.println("jsTicket = " + jsTicket);
		 * System.out.println("&appId = " + sign.getAppId());
		 * System.out.println("&nonceStr = "+sign.getNonceStr());
		 * System.out.println("&timestamp = " + sign.getTimestamp());
		 * System.out.println("&url = " + url);
		 * System.out.println("&signature = " + sign.getSignature());
		 */

		JsonView jv = new JsonView();
		jv.setData(sign);

		return jv.toString();
	}

	
	/**
	 * 增加用户的微信关系
	 * @param request
	 * @param openid
	 * @param id
	 * @return
	 */
	@RequestMapping(value = "/binding", method = RequestMethod.POST)
	@ResponseBody
	public Object binding(HttpServletRequest request,HttpSession session,String openid, int id, String recommendCode){
		int i = myService.binding(openid,id);
		JsonView jv = new JsonView();
		if(i>0){
			jv.setMessage("ok");
			jv.setData("ok");
			UserInfo userInfo = userInfoBo.queryBindingUserInfoById(id);
			if(userInfo != null){
				session.setAttribute(GlobalConstant.USER_INFO, userInfo);
			}
			ShareMemberInfo memberInfo = new ShareMemberInfo();
			memberInfo.setUserId(userInfo.getId());
			memberInfo.setShareCode(recommendCode);
			memberInfo.setRegisterTime(new Date());
			memberInfo.setIsPayStatus(0);
			shareMemberBo.txInsert(memberInfo);
			
		}else{
			jv.setErrcode(999);
			jv.setMessage("error");
			jv.setData("error");
		}
		return jv;
	}

	/**
	 * 解除用户的微信关系
	 * @param request
	 * @param id
	 * @return
	 */
	@RequestMapping(value = "/unbind", method = RequestMethod.POST)
	@ResponseBody
	public Object unbind(HttpSession session,HttpServletRequest request, int id){
		int i = myService.unbind(id);
		JsonView jv = new JsonView();
		if(i>0){
			//session.invalidate(); //每次登录清除Session缓存
			session = request.getSession();
			jv.setMessage("ok");
			jv.setData("ok");
		}else{
			jv.setErrcode(999);
			jv.setMessage("error");
			jv.setData("error");
		}
		return jv;
	}
	
	/**
	 * 确认可绑定
	 * @param request
	 * @param openid
	 * @param id
	 * @return
	 */
	@RequestMapping(value = "/checkInfo", method = RequestMethod.POST)
//	@RequestMapping(value = "/checkInfo")
	@ResponseBody
	public Object checkInfo(HttpServletRequest request,String openid, int id){
		int i = myService.checkInfo(openid,id);
		JsonView jv = new JsonView();
		if(i==0){
			jv.setMessage("ok");
			jv.setData("ok");
		}else if(i==1){
			jv.setErrcode(i);
			jv.setMessage("该微信号已绑定其他账户，请解除绑定重新操作");
			jv.setData(i);
		}else if(i==2){
			jv.setErrcode(i);
			jv.setMessage("该账户已绑定其他微信号");
			jv.setData(i);
		}else if(i==3){
			jv.setErrcode(i);
			jv.setMessage("数据异常");
			jv.setData(i);
		}else if(i==4){
			jv.setErrcode(i);
			jv.setMessage("该账户已经与该微信号绑定");
			jv.setData(i);
		}
		return jv;
	}
	
	
	/**
	 * 清除token
	 * @param request
	 * @param account
	 * @return
	 */
	@RequestMapping(value = "/clearToken/{account}")
	@ResponseBody
	public Object clearToken(HttpServletRequest request,
			@PathVariable String account){
		WxMemoryCacheClient.cleartoken(account);
		return "ok";
	}
	
	
	/**
	 * 获取账号的APPID
	 * @param request
	 * @param account
	 * @return
	 */
	@RequestMapping(value = "/getAppid/{account}")
	@ResponseBody
	public Object getAccount(HttpServletRequest request,
			@PathVariable String account){
		MpAccount mpAccount = WxMemoryCacheClient.getMpAccount(account);
		if (mpAccount == null) {
			mpAccount = myService.getAccount(account);
		}
		return mpAccount.getAppid();
	}
	
	/**
	 * 新用户微信授权验证手机后绑定信息
	 * @param info
	 * @return 0:fail 1：success
	 * @author Javin : isUer = true
	 */
	@RequestMapping("/insertWechatInfo")
	@ResponseBody
	public Object insertWechatInfo(UserInfo info,HttpSession session){
		return userInfoBo.txInsertWechatInfo(info,session);
	}
	
}
